#pragma once
#include "Connection.hpp"
#include <unordered_map>
#include <sys/epoll.h>
#include "Epoller.hpp"
class Connection;

class Reactor
{
    static const int gnum = 64;
public:
    Reactor() : _isrunning(false)
    {

    }
    ~Reactor() {}
    void AddConnection(int fd, uint32_t events, func_t recv, func_t send, func_t except)
    {

        // 1、构建Connection
        Connection *conn = new Connection(fd);

        conn->Register(recv, send, except);

        conn->SetReactor(this);

        conn->SetEvents(events);

        // 2、把connection添加进connections进行管理
        _connections[fd] = conn;

        // 3、向内核设置对事件的关心

        _epoller.AddEvent(conn->Sockfd(), conn->Events());
    }
    bool ConnectionIsExist(int sockfd)
    {
        if (_connections.find(sockfd) == _connections.end())
            return false;
        return true;
    }
    void Dispatcher()
    {
        _isrunning = true;
        int timeout = -1;
        while (_isrunning)
        {
            int n = _epoller.Wait(_revents, timeout, gnum);
            if (n > 0)
            {
                // 事件派发
                for (int i = 0; i < n; ++i)
                {
                    int sockfd = _revents[i].data.fd;
                    uint32_t revent = _revents[i].events;
                    if (revent & EPOLLHUP)
                        revent |= (EPOLLIN | EPOLLOUT);
                    if (revent & EPOLLERR)
                        revent |= (EPOLLIN | EPOLLOUT);

                    if (revent & EPOLLIN)
                    {
                        if (ConnectionIsExist(sockfd) && _connections[sockfd]->_recv != nullptr)
                        {
                            _connections[sockfd]->_recv(_connections[sockfd]);
                        }
                    }
                    if (revent & EPOLLOUT)
                    {
                        if (ConnectionIsExist(sockfd) && _connections[sockfd]->_send != nullptr)
                        {
                            _connections[sockfd]->_send(_connections[sockfd]);
                        }
                    }
                }
            }
        }
    }

private:
    Epoller _epoller;
    struct epoll_event _revents[gnum];
    bool _isrunning;
    std::unordered_map<int, Connection*> _connections;
};